package com.websocket.otp;

import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.UndeclaredThrowableException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

public class TOTP {
    private static final int TIME_STEP = 30; // 时间步长，单位为秒
    private static final int TOTP_LENGTH = 10; // 动态验证码长度
    private static final String HMAC_ALGORITHM = "HmacSHA1"; // HMAC 算法

    // 生成动态验证码
    public static String generateTOTP(String appKey, String secretKey, String sequence) {
        long counter = Instant.now().getEpochSecond() / TIME_STEP; // 计算计数器值
        byte[] counterBytes = ByteBuffer.allocate(8).putLong(counter).array(); // 将计数器转换为字节数组

        byte[] secretKeyBytes = secretKey.getBytes(); // 将密钥转换为字节数组
        byte[] appKeyBytes = appKey.getBytes(); // 将应用密钥转换为字节数组
        byte[] sequenceBytes = sequence.getBytes();
        // 计算 HMAC 值
        byte[] hmacValue = null;
        try {
            Mac hmac = Mac.getInstance(HMAC_ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(secretKeyBytes, HMAC_ALGORITHM);
            hmac.init(keySpec);
            hmac.update(appKeyBytes); // 添加应用密钥
            hmac.update(sequenceBytes);
            hmacValue = hmac.doFinal(counterBytes);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }

        // 截取动态验证码
        int offset = hmacValue[hmacValue.length - 1] & 0x0F;
        int binary = ((hmacValue[offset] & 0x7F) << 24) |
                ((hmacValue[offset + 1] & 0xFF) << 16) |
                ((hmacValue[offset + 2] & 0xFF) << 8) |
                (hmacValue[offset + 3] & 0xFF);
        int otp = binary % (int) Math.pow(10, TOTP_LENGTH);
        return StringUtils.rightPad(String.format("%06d", otp),TOTP_LENGTH,"0");
    }

    // 验证动态验证码
    public static boolean validateTOTP(String appKey, String secretKey, String sequence, String code) {
        // 生成预期的动态验证码
        String expectedCode = generateTOTP(appKey, secretKey, sequence);
        // 比较验证码是否匹配
        return expectedCode.equals(code);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {

            // 应用密钥
            String appKey = "rdlp";
            // 密钥
            String secretKey = "adadadsad";
            String sequence = SnowflakeIdGenerator.getInstance().nextId() + "";
            // 生成并输出动态验证码
            String totp = generateTOTP(appKey, secretKey, sequence);
            System.out.println("动态验证码: " + i +" = " + totp);
            System.out.println("动态验证码: "  + i +" = " + validateTOTP(appKey, secretKey, sequence, totp));
            System.out.println("动态验证码: "  + i + 1 +" = " + validateTOTP(appKey, secretKey, sequence, totp));
        }


    }


}
